package com.sky.chapter3.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * 你以为A一直是A 但其实A已经变成过B之后又变回了A
 *
 * 例如: 潘金莲A 被 西门庆动过了手脚成为 B, 但是又去某医院 做了修复手术成为了A 想要蒙混过关 , 那么武大郎是如何知道潘金莲是否被动过的呢???
 *
 * */
public class CASDemo {

    //AtomicStampedReference 注意，如果泛型是一个包装类，注意对象的引用问题

    // 正常在业务操作，这里面比较的都是一个个对象, 这个原子类底层使用了cas这个理论;
    private  static AtomicStampedReference<Integer> referencePan
            = new AtomicStampedReference<>(1,1); //给潘金莲加上监视器

    // CAS  compareAndSet : 比较并交换！
    public static void main(String[] args) {



        /*潘金莲去做衣服*/
        new Thread(()->{
            int stamp = referencePan.getStamp(); // 获得版本号   (监视器的值)
            System.out.println("a1=>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            Lock lock = new ReentrantLock(true);

            referencePan.compareAndSet(1, 2, referencePan.getStamp(), referencePan.getStamp() + 1);  //破坏

            System.out.println("a2=>"+ referencePan.getStamp());

            System.out.println(referencePan.compareAndSet(2, 1, referencePan.getStamp(),
                    referencePan.getStamp() + 1));  //去医院修复

            System.out.println("a3=>"+ referencePan.getStamp());

        },"西门庆").start();


        /*潘金莲晚上回家*/
        new Thread(()->{
            int stamp = referencePan.getStamp(); // 获得版本号
            System.out.println("b1=>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println( "潘金莲是否冰清玉洁? " +  referencePan.compareAndSet(1, 6, stamp, stamp + 1));

            System.out.println("b2=>"+ referencePan.getStamp());

        },"武大郎").start();

    }
}
